/**
 * 
 */
package com.xpec.c4.service.module;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.service.consistenthash.ConsistentHash;

/**
 * 依據群組名稱分類，並使用guid做一致性的分配
 * 
 * @author TW15010
 */
public class ConsistentGroupName {
	// log object
	private static final Log log = LogFactory.getLog(ConsistentGroupName.class);

	/**
	 * 依據群組名稱分類，並使用guid做一致性的分配
	 */
	private static ConcurrentHashMap<String, ConsistentHash<String>> consistentMap;

	private static ConcurrentHashMap<String, Set<String>> groupMap;

	public static ConcurrentHashMap<String, Set<String>> getGroupMap() {
		return groupMap;
	}

	/**
	 * 初始化
	 */
	public static void initial() {
		if (consistentMap != null && groupMap != null) {
			return;
		}

		consistentMap = new ConcurrentHashMap<String, ConsistentHash<String>>();
		groupMap = new ConcurrentHashMap<String, Set<String>>();

		// 一般game server
		registerConsistentGroupName(ModuleName.GROUP_ACCOUNT_PLAYER);
		registerConsistentGroupName(ModuleName.GROUP_LOGIN_PLAYER);
		registerConsistentGroupName(ModuleName.GROUP_LOGIN_ROBOT);
		registerConsistentGroupName(ModuleName.GROUP_GAMELOBBY_PLAYER);
		registerConsistentGroupName(ModuleName.GROUP_GAMELOBBY_ROBOT);
		registerConsistentGroupName(ModuleName.GROUP_DATA_CENTER);

		// 遊戲記錄回傳
		registerConsistentGroupName(ModuleName.GROUP_LOGSPOUT);

		// 統計群
		registerConsistentGroupName(ModuleName.GROUP_ANALYSIS);

		// 任務群
		registerConsistentGroupName(ModuleName.GROUP_MISSION);

		// 跑馬燈群
		registerConsistentGroupName(ModuleName.GROUP_MARQUEE_COLLECTOR);

		// 福袋群
		registerConsistentGroupName(ModuleName.GROUP_BONUS_PACK);

		// 角色名稱檢查群
		registerConsistentGroupName(ModuleName.GROUP_PLAYER_NAME_VERIFY);

		// 排行榜收集
		registerConsistentGroupName(ModuleName.GROUP_RANK_COLLECTOR);
		
		// 捕鱼
		registerConsistentGroupName(ModuleName.GROUP_FISH);
//		registerConsistentGroupName(ModuleName.GROUP_RBT_FISH);
	}

	/**
	 * 註冊群組module name
	 * game_info.propertes.group_xxx = module1,moudle2
	 */
	private static void registerConsistentGroupName(String name) {
		if (consistentMap == null) {
			return;
		}

		try {
			String group = ServerProperties.getProperty("group_" + name);
			String[] glist = group.split(",");

			Set<String> node = new HashSet<String>();
			for (String n : glist) {
				node.add(n);
			}
			groupMap.put(name, node);

			ConsistentHash<String> hash = new ConsistentHash<String>(160, node);
			consistentMap.put(name, hash);
		} catch (Exception e) {
			log.error(e, e);
		}
	}

	/**
	 * 註冊自訂的群組, 不限於 module name
	 * 
	 * @param name
	 *            群組名稱
	 * @param node
	 *            要被分配的項目字串表
	 */
	public static void registerCustomConsistentGroupName(String name, Set<String> node) {
		if (consistentMap == null) {
			return;
		}

		try {
			groupMap.put(name, node);

			ConsistentHash<String> hash = new ConsistentHash<String>(160, node);
			consistentMap.put(name, hash);
		} catch (Exception e) {
			log.error(e, e);
		}
	}

	/**
	 * 檢查指定的名稱是否存在群組中
	 * 
	 * @param groupName
	 *            群組名稱, {@link ModuleName}
	 * @param name
	 * @return
	 */
	public static boolean isExistInGroup(String groupName, String name) {
		if (consistentMap == null) {
			return false;
		}

		ConsistentHash<String> hash = consistentMap.get(groupName);
		if (hash == null) {
			return false;
		}

		Set<String> node = hash.getOrgNodes();
		if (node == null) {
			return false;
		}

		boolean exist = node.contains(name);

		return exist;
	}

	/**
	 * 讀取多個相同module時，分配至何module
	 * 
	 * @return
	 */
	public static String lookUp(String groupname, GUID player) {
		if (consistentMap == null) {
			return null;
		}

		if (!consistentMap.containsKey(groupname)) {
			return null;
		}

		ConsistentHash<String> look = consistentMap.get(groupname);
		String result = "";
		try {
			result = look.get(player.toString());
		} catch (Exception e) {
			result = look.getFirstValue();
			if (log.isErrorEnabled()) {
				log.error("Player " + player.toString() + " Look Up Fail ! Want : " + groupname + " use : "
						+ result, e);
			}
		}
		return result;
	}

	/**
	 * 讀取多個相同module時，分配至何module
	 * 
	 * @return
	 */
	public static String lookUpByString(String groupname, String key) {
		if (consistentMap == null) {
			return null;
		}

		if (!consistentMap.containsKey(groupname)) {
			return null;
		}

		ConsistentHash<String> look = consistentMap.get(groupname);

		String result = "";
		try {
			result = look.get(key);
		} catch (Exception e) {
			result = look.getFirstValue();
			if (log.isErrorEnabled()) {
				log.error("Key " + key + " Look Up Fail ! Want : " + groupname + " use : " + result, e);
			}
		}
		return result;
	}

	/**
	 * 用 account id 決定要分配到哪個 login modul
	 * 
	 * @param accountId
	 * @param isRobot
	 * @return
	 */
	public static String lookUpLoginModule(GUID accountId, boolean isRobot) {
		String groupName;
		if (isRobot) {
			groupName = ModuleName.GROUP_LOGIN_ROBOT;
		} else {
			groupName = ModuleName.GROUP_LOGIN_PLAYER;
		}

		return lookUp(groupName, accountId);
	}

	/**
	 * 用 player id 決定要分配到哪個 gamelobby modul
	 * 
	 * @param playerId
	 * @param isRobot
	 * @return
	 */
	public static String lookUpGameLobbyModule(GUID playerId, boolean isRobot) {
		String groupName;
		if (isRobot) {
			groupName = ModuleName.GROUP_GAMELOBBY_ROBOT;
		} else {
			groupName = ModuleName.GROUP_GAMELOBBY_PLAYER;
		}

		return lookUp(groupName, playerId);
	}
}
